package com.fzu.geometa.metadata.service.impl;

import com.fzu.geometa.common.exception.GeometaException;
import com.fzu.geometa.metadata.model.po.Item;
import com.fzu.geometa.metadata.model.po.Register;
import com.fzu.geometa.metadata.service.*;
import com.fzu.geometa.metadata.util.RedisKeyUtils;
import com.fzu.geometa.metadata.util.ValidateClient;
import com.fzu.geometa.metadata.util.XmlUtils;
import org.dom4j.DocumentException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.Optional;

import static com.fzu.geometa.metadata.common.RegisterConst.VALIDATE_ON;

@Service
@Transactional
public class ItemValidateServiceImpl implements ItemValidateService {
    @Autowired
    RegisterService registerService;
    @Autowired
    MetadataService metadataService;
    @Autowired
    ItemService itemService;

    @Autowired
    NamespaceService namespaceService;

    @Autowired
    ValidateClient validateClient;

    @Autowired
    RedisTemplate<String, String> redisTemplate;

    // 更新并验证
    @Override
    public boolean updateWithValidation(Item item) {
        //  更新
        boolean res = itemService.updateById(item);
        // 可能没 cid
        item = itemService.getById(item.getEid());
        // 验证
        validateDocument(item.getCid());
        // 缓存失效
        removeFromCache(item.getCid());
        return res;
    }

    // 添加并验证
    @Override
    public boolean addWithValidation(Item item) {
        boolean isSucceed = itemService.addItemAndAdjustTree(item);
        if (!isSucceed) {
            // 没有添加成功
            return false;
        }
        // 必须验证命名空间，非法的命名空间会使 dom4j 无法生成文档
        if (!namespaceService.
                isValidNamespace(
                        item.getCid(), item.getNamespace())) {
            throw new GeometaException("非法的命名空间");

        }
        validateDocument(item.getCid());
        // 缓存失效
        removeFromCache(item.getCid());
        return true;
    }

    // 删除并验证
    @Override
    public boolean deleteWithValidation(Long eid) {
        Item item = itemService.getById(eid);
        boolean res = itemService.removeItemAndChildren(eid);
        validateDocument(item.getCid());
        // 缓存失效
        removeFromCache(item.getCid());
        return res;
    }

    /**
     * 文档验证
     *
     * @param cid 文档标识
     */
    public void validateDocument(Long cid) {
        Register register = registerService.getById(cid);
        if (register == null) {
            throw new GeometaException("非法数据，未注册");
        }
        // 是否开启了验证
        Boolean validateOn = Optional.ofNullable(register)
                .map(Register::getValidate)
                .map(v -> v == VALIDATE_ON)
                .orElse(false);

        if (validateOn) {
            String metadata = metadataService.getMetadata(cid);
            boolean passed = validateClient.validate(register.getStandard(), register.getSubtype(), metadata);
            if (!passed) {
                throw new GeometaException("数据更新失败，未通过验证");
            }
        }
    }

    // 移除缓存
    public void removeFromCache(Long cid) {
        String coverageId = registerService.getCoverageIdByCid(cid);
        String key = RedisKeyUtils.getMetadataKey(coverageId);
        redisTemplate.delete(key);
    }
}
